package at.donalfonso.utility;

import java.util.ArrayList;

import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.Topic;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.broker.BrokerService;
import org.apache.activemq.network.NetworkConnector;

/**
 * Bündelt JMS Funktionalität (Connections, Sessions, ...) analog zur
 * Klasse Space.
 * @author jan
 *
 */
public class JMSUtility {

	private static final String URL_FILIALE1 = "tcp://localhost:61616";
	//private static final String URL_FILIALE2 = "tcp://localhost:61617";

	private String URL = URL_FILIALE1;
	
	public static final String QUEUE_KUECHE_INPUT 		= "queue.kueche.input";
	public static final String QUEUE_KUECHE_OUTPUT 	    = "queue.kueche.output";
	public static final String QUEUE_BESTELLUNG_NEU		= "queue.bestellung.neu";
	public static final String QUEUE_BESTELLUNG_OFFEN 	= "queue.bestellung.offen";
	public static final String QUEUE_BESTELLUNG_FERTIG  = "queue.bestellung.fertig";
	public static final String QUEUE_BESTELLUNG_AUFGENOMMEN  = "queue.bestellung.aufgenommen";
	public static final String QUEUE_SAAL 				= "queue.saal";
	public static final String QUEUE_EINGANG 			= "queue.eingang";
	public static final String QUEUE_TISCH				= "queue.tisch";
	public static final String QUEUE_LIEFERUNG			= "queue.lieferung";

	public static final String TOPIC_GUI_UPDATE			= "topic.gui.update";
	public static final String TOPIC_LIEFERUNG			= "topic.lieferung";

	private ActiveMQConnectionFactory connectionFactory = null;
	private Connection connection = null;
	private Session session = null;

	private Queue queueKuecheInput 		= null;
	private Queue queueKuecheOutput 	= null;
	private Queue queueBestellungNeu	= null;
	private Queue queueBestellungOffen 	= null;
	private Queue queueBestellungFertig = null;
	private Queue queueBestellungAufgenommen = null;
	private Queue queueSaal 			= null;
	private Queue queueEingang 			= null;
	private Queue queueTisch			= null;
	private Queue queueLieferung		= null;

	private Topic topicGuiUpdate = null;
	private Topic topicLieferung = null;
	
	private BrokerService broker = null;

	private int filiale;

	
	/**
	 * Wird im Benchmark verwendet um den Broker zurückzusetzen.
	 * @param args
	 */
	public static void main(String [] args){
		try{
			System.out.println("Purging all queues:");
			JMSUtility utility1 = new JMSUtility(1);
			JMSUtility utility2 = new JMSUtility(2);
			
			utility1.getConnection().start();
			utility2.getConnection().start();
			
			utility1.purgeQueues();
			utility2.purgeQueues();
			
			System.exit(0);
		}catch(Exception e){
			
		}
	}
		
	
	public JMSUtility(int filiale) {
		
		this.filiale = filiale;
		
		if (filiale != 1 && filiale != 2){
			System.out.println("Bitte geben sie entweder 1 oder 2 als Filiale an.");
		}		
		
		System.out.println("JMS Utility ... initialisiert. Filiale: "+filiale);
	}

	public ActiveMQConnectionFactory getFactory() {
		if (connectionFactory == null){
			connectionFactory = new ActiveMQConnectionFactory(URL);
		}
		return connectionFactory;
	}

	public Connection getConnection() throws JMSException{
		if (connection == null){
			connection = getFactory().createConnection();
		}
		return connection; 
	}

	public Session getSession() throws JMSException{
		if (session == null){
			session = getConnection().createSession(false, Session.AUTO_ACKNOWLEDGE);
		}
		return session; 
	}

	public Topic getTopicGuiUpdate() throws JMSException {
		if (topicGuiUpdate == null){
			topicGuiUpdate = getSession().createTopic(filiale+"."+TOPIC_GUI_UPDATE);
		}
		return topicGuiUpdate;
	}
	
	/** 
	 * Wird im Loadbalancer verwendet um festzustellen wieviele Liefer-
	 * bestellungen offen sind.
	 * @return
	 * @throws JMSException
	 */
	public Topic getTopicLieferung() throws JMSException {
		if (topicLieferung == null){
			topicLieferung = getSession().createTopic(filiale+"."+TOPIC_LIEFERUNG);
		}
		return topicLieferung;
	}

	public Topic createTopicGuiUpdate(int filiale) throws JMSException {
		return getSession().createTopic(filiale+"."+TOPIC_GUI_UPDATE);
	}
	
	public Queue getQueueKuecheInput() throws JMSException {
		if (queueKuecheInput == null){
			queueKuecheInput = getSession().createQueue(filiale+"."+QUEUE_KUECHE_INPUT);
		}
		return queueKuecheInput;
	}

	public Queue getQueueKuecheOutput() throws JMSException {
		if (queueKuecheOutput == null){
			queueKuecheOutput = getSession().createQueue(filiale+"."+QUEUE_KUECHE_OUTPUT);
		}
		return queueKuecheOutput;
	}

	public Queue getQueueBestellungNeu() throws JMSException {
		if (queueBestellungNeu == null){
			queueBestellungNeu = getSession().createQueue(filiale+"."+QUEUE_BESTELLUNG_NEU);
		}
		return queueBestellungNeu;
	}

	public Queue getQueueBestellungOffen() throws JMSException {
		if (queueBestellungOffen == null){
			queueBestellungOffen = getSession().createQueue(filiale+"."+QUEUE_BESTELLUNG_OFFEN);
		}
		return queueBestellungOffen;
	}

	public Queue getQueueBestellungFertig() throws JMSException {
		if (queueBestellungFertig == null){
			queueBestellungFertig = getSession().createQueue(filiale+"."+QUEUE_BESTELLUNG_FERTIG);
		}
		return queueBestellungFertig;
	}
	
	public Queue getQueueBestellungAufgenommen() throws JMSException {
		if (queueBestellungAufgenommen == null){
			queueBestellungAufgenommen = getSession().createQueue(filiale+"."+QUEUE_BESTELLUNG_AUFGENOMMEN);
		}
		return queueBestellungAufgenommen;
	}

	public Queue getQueueSaal() throws JMSException {
		if (queueSaal == null){
			queueSaal = getSession().createQueue(filiale+"."+QUEUE_SAAL);
		}
		return queueSaal;
	}

	public Queue getQueueEingang() throws JMSException {
		if (queueEingang == null){
			queueEingang = getSession().createQueue(filiale+"."+QUEUE_EINGANG);
		}
		return queueEingang;
	}

	public Queue getQueueTisch() throws JMSException {
		if (queueTisch == null) {
			queueTisch = getSession().createQueue(filiale+"."+QUEUE_TISCH);
		}
		return queueTisch;
	}
	
	public Queue getQueueLieferung() throws JMSException {
		if (queueLieferung == null) {
			queueLieferung = getSession().createQueue(filiale+"."+QUEUE_LIEFERUNG);
		}
		return queueLieferung;
	}

	public void purgeQueues(){
		try {

			System.out.println("Start purging queues ...");
			
			MessageConsumer consumer;
			ArrayList<Destination> queues = new ArrayList<Destination>();
			
			queues.add(getQueueBestellungFertig());
			queues.add(getQueueBestellungNeu());
			queues.add(getQueueBestellungOffen());
			queues.add(getQueueEingang());
			queues.add(getQueueKuecheInput());
			queues.add(getQueueKuecheOutput());
			queues.add(getQueueLieferung());
			queues.add(getQueueSaal());
			queues.add(getQueueTisch());
			queues.add(getQueueBestellungAufgenommen());
			queues.add(getTopicLieferung());
			queues.add(getTopicGuiUpdate());
			
			for (Destination queue : queues){
				System.out.println("Purging queue: "+queue);
				consumer = getSession().createConsumer(queue);
				while (consumer.receive(1000) != null);
				consumer.close();
			}
			
			System.out.println("Purging finished");
			
		} catch (JMSException e) {
			e.printStackTrace();
		}
	}
	
	public void runBroker(){
		try {
			System.out.println("Starte Broker: "+URL);
			broker = new BrokerService();
			broker.setUseShutdownHook(false);

			broker.addConnector(URL);
			broker.start();	
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public BrokerService getBroker(){
		return broker;
	}	
}
